"""
SAR策略示例
演示如何使用和测试SAR策略
"""
import sys
import os
import asyncio
import pandas as pd
import numpy as np
import logging
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
import argparse
import json
import warnings
import re
import ast

# 添加项目根目录到Python路径，确保可以导入项目模块
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from services.strategies.implementations.sar_strategy import SARStrategy
from utils.indicators import Indicators
from models.base import SessionLocal
from models.kline_5min import Kline5Min
from models.strategy_config import StrategyConfig

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger("sar_example")

# 创建一个新的NullHandler来禁止日志输出
class SilentHandler(logging.Handler):
    def emit(self, record):
        pass

def load_data_from_db(db: Session, symbol: str, limit: int = 1000) -> pd.DataFrame:
    """
    从数据库加载K线数据 (重构后)
    """
    logger.info(f"从数据库加载 {symbol} 的 {limit} 条5分钟K线数据...")
    
    # 1. 创建查询
    query = (
        db.query(Kline5Min)
        .filter(Kline5Min.symbol == symbol.replace("_", "-"))
        .order_by(Kline5Min.datetime.desc())
        .limit(limit)
    )
    
    # 2. 执行查询并获取结果
    results = query.all()
    
    if not results:
        raise ValueError(f"数据库中未找到交易对 {symbol} 的数据")
        
    # 3. 将ORM对象列表转换为字典列表
    data = [
        {
            "datetime": r.datetime,
            "open": float(r.open),
            "high": float(r.high),
            "low": float(r.low),
            "close": float(r.close),
            "volume": float(r.volume),
        }
        for r in results
    ]
    
    # 4. 创建DataFrame
    df = pd.DataFrame(data)
    
    # 5. 按时间升序排列
    df = df.sort_values('datetime').reset_index(drop=True)
    logger.info(f"成功加载 {len(df)} 条数据")
    return df

def generate_backtest_report(completed_pairs: list, prepared_data: pd.DataFrame, symbol: str, days: int, show_details: bool):
    """
    生成并打印详细的回测报告
    """
    if not completed_pairs:
        logger.warning("没有完成的交易对，无法生成报告。")
        return

    # --- 基本信息 ---
    start_date = prepared_data['datetime'].iloc[0].strftime('%Y-%m-%d')
    end_date = prepared_data['datetime'].iloc[-1].strftime('%Y-%m-%d')
    
    # --- 杠杆和保证金设置 ---
    leverage = 25  # 30倍杠杆
    margin = 10.0  # 50U保证金
    
    # --- 核心绩效指标计算 ---
    initial_capital = margin * leverage  # 杠杆后的名义本金
    equity = margin  # 实际权益从保证金开始计算
    peak_equity = margin
    max_drawdown = 0.0
    equity_curve = []
    
    # 计算交易费用和杠杆后的收益
    total_fees = 0
    for pair in completed_pairs:
        # 计算开仓和平仓手续费
        entry_fee = margin * leverage * 0.0005
        exit_fee = margin * leverage * 0.0005
        trade_fees = entry_fee + exit_fee
        total_fees += trade_fees
        
        # 计算该笔交易的盈亏金额（考虑杠杆和手续费）
        pnl_ratio = pair['pnl_percent'] / 100
        pnl_amount_before_fees = margin * pnl_ratio * leverage
        pnl_amount = pnl_amount_before_fees - trade_fees
        
        # 更新权益
        equity += pnl_amount
        equity_curve.append(equity)
        
        # 更新最大回撤
        if equity > peak_equity:
            peak_equity = equity
        drawdown = (peak_equity - equity) / peak_equity
        if drawdown > max_drawdown:
            max_drawdown = drawdown
            
        # 更新交易对中的杠杆收益信息和手续费
        pair['leveraged_pnl_percent'] = pnl_ratio * leverage * 100
        pair['fees'] = trade_fees
        pair['pnl_amount_before_fees'] = pnl_amount_before_fees
        pair['pnl_amount'] = pnl_amount

    # 计算总收益率（基于保证金）
    total_pnl_percent = ((equity / margin) - 1) * 100
    
    # 计算月收益率（基于当前收益率和回测天数）
    monthly_return = ((1 + total_pnl_percent / 100) ** (30 / days) - 1) * 100 if days > 0 else 0
    
    # 计算年化收益率
    annual_return = ((1 + total_pnl_percent / 100) ** (365 / days) - 1) * 100 if days > 0 else 0
    
    # 计算夏普比率 (假设无风险利率为0)
    returns = [p['leveraged_pnl_percent'] / 100 for p in completed_pairs]
    returns_series = pd.Series(returns)
    sharpe_ratio = returns_series.mean() / returns_series.std() * np.sqrt(len(completed_pairs)) if returns_series.std() > 0 else 0

    # --- 交易统计 ---
    total_trades = len(completed_pairs)
    win_trades = [p for p in completed_pairs if p['pnl_percent'] > 0]
    loss_trades = [p for p in completed_pairs if p['pnl_percent'] <= 0]
    
    win_rate = len(win_trades) / total_trades * 100 if total_trades > 0 else 0
    
    avg_win_pnl = np.mean([p['leveraged_pnl_percent'] for p in win_trades]) if win_trades else 0
    avg_loss_pnl = np.mean([p['leveraged_pnl_percent'] for p in loss_trades]) if loss_trades else 0
    
    profit_loss_ratio = abs(avg_win_pnl / avg_loss_pnl) if avg_loss_pnl != 0 else float('inf')
    
    max_win = max([p['leveraged_pnl_percent'] for p in win_trades]) if win_trades else 0
    max_loss = min([p['leveraged_pnl_percent'] for p in loss_trades]) if loss_trades else 0
    
    # --- 持仓时间 ---
    holding_periods = [(p['exit']['datetime'] - p['entry']['datetime']) for p in completed_pairs]
    avg_holding_period = np.mean(holding_periods) if holding_periods else timedelta(0)
    
    # --- 交易频率 ---
    trades_per_day = total_trades / days if days > 0 else 0
    estimated_monthly_trades = trades_per_day * 30

    # --- 打印报告 ---
    report = f"""
    ======================================================================
    |                         SAR策略回测报告                          |
    ======================================================================
    
    一、回测配置
    ----------------------------------------------------------------------
    交易对: {symbol}
    回测周期: {start_date} to {end_date} ({days} 天)
    K线间隔: 5 分钟
    杠杆倍数: {leverage}x
    保证金: {margin} USDT
    手续费率: 0.05% (开仓) + 0.05% (平仓)
    
    二、核心绩效
    ----------------------------------------------------------------------
    初始保证金:     {margin:.2f} USDT
    最终权益:       {equity:.2f} USDT
    总收益率:       {total_pnl_percent:.2f}%
    月化收益率:     {monthly_return:.2f}%
    年化收益率:     {annual_return:.2f}%
    最大回撤:       {max_drawdown*100:.2f}%
    夏普比率:       {sharpe_ratio:.2f}
    总手续费:       {total_fees:.2f} USDT
    
    三、交易统计
    ----------------------------------------------------------------------
    总交易次数:     {total_trades}
    每日平均交易:   {trades_per_day:.2f}
    预计月交易量:   {estimated_monthly_trades:.0f}
    盈利交易:       {len(win_trades)}
    亏损交易:       {len(loss_trades)}
    胜率:           {win_rate:.2f}%
    盈亏比:         {profit_loss_ratio:.2f}
    平均每笔盈利:   {avg_win_pnl:.2f}% (含杠杆)
    平均每笔亏损:   {avg_loss_pnl:.2f}% (含杠杆)
    最大单笔盈利:   {max_win:.2f}% (含杠杆)
    最大单笔亏损:   {max_loss:.2f}% (含杠杆)
    平均持仓时间:   {str(avg_holding_period).split('.')[0]}
    平均每笔手续费: {total_fees/total_trades:.2f} USDT
    
    """
    
    # --- 打印交易详情表格 ---
    if show_details and completed_pairs:
        trade_details_header = """
    四、交易详情
    -------------------------------------------------------------------------------------------------------------------------------------------------
    | #  | 方向 | 开仓时间          |   开仓价   | 平仓时间          |   平仓价   | 平仓原因     | 盈亏(%)  | 杠杆盈亏(%) | 手续费(U) | 实际盈亏(U) | 持仓时间        |
    |----|------|-------------------|------------|-------------------|------------|--------------|----------|-------------|-----------|-------------|-----------------|
"""
        trade_details_rows = ""
        for i, pair in enumerate(completed_pairs):
            holding_period = pair['exit']['datetime'] - pair['entry']['datetime']
            direction_str = pair['entry']['direction']
            exit_reason = pair['exit'].get('reason', 'unknown')
            trade_details_rows += (
                f"| {i+1:<2} |  {direction_str}   | "
                f"{pair['entry']['datetime'].strftime('%Y-%m-%d %H:%M')}   | "
                f"{pair['entry']['price']:>10.6f} | "
                f"{pair['exit']['datetime'].strftime('%Y-%m-%d %H:%M')}   | "
                f"{pair['exit']['price']:>10.6f} | "
                f"{exit_reason:<12} | "
                f"{pair['pnl_percent']:>8.2f} | "
                f"{pair['leveraged_pnl_percent']:>11.2f} | "
                f"{pair['fees']:>9.2f} | "
                f"{pair['pnl_amount']:>11.2f} | "
                f"{str(holding_period).split('.')[0]:<15} |\n"
            )
        
        trade_details_footer = "    -------------------------------------------------------------------------------------------------------------------------------------------------"
        
        report += trade_details_header + trade_details_rows + trade_details_footer

    print(report)
    
    # 打印最终权益
    logger.info(f"初始保证金: {margin:.2f} USDT, 最终权益: {equity:.2f} USDT (收益率: {total_pnl_percent:.2f}%, 月化收益: {monthly_return:.2f}%)")

def generate_summary_report(all_trades: list):
    """
    生成所有交易对的交易详情汇总报告，包括同时持有币种的分析
    """
    if not all_trades:
        return
        
    # 分析同一时间最多持有几个币种
    max_concurrent, max_details, max_time = analyze_concurrent_positions(all_trades)

    # --- 1. 打印所有交易详情表 ---
    report = f"""
    =======================================================================================================================================================
    |                                                           交易详情总汇                                                                      |
    =======================================================================================================================================================
    """
    
    trade_details_header = """
    | #  | 交易对       | 方向 | 开仓时间          |   开仓价   | 平仓时间          |   平仓价   | 平仓原因     | 盈亏(%)  | 杠杆盈亏(%) | 盈亏金额(U) | 持仓时间        |
    |----|--------------|------|-------------------|------------|-------------------|------------|--------------|----------|-------------|-------------|-----------------|
"""
    trade_details_rows = ""
    # 按开仓时间对所有交易进行排序
    all_trades.sort(key=lambda x: x['entry']['datetime'])

    for i, pair in enumerate(all_trades):
        holding_period = pair['exit']['datetime'] - pair['entry']['datetime']
        direction_str = pair['entry']['direction']
        symbol_str = pair['symbol']
        exit_reason = pair['exit'].get('reason', 'unknown')
        trade_details_rows += (
            f"| {i+1:<2} | {symbol_str:<12} |  {direction_str}   | "
            f"{pair['entry']['datetime'].strftime('%Y-%m-%d %H:%M')}   | "
            f"{pair['entry']['price']:>10.6f} | "
            f"{pair['exit']['datetime'].strftime('%Y-%m-%d %H:%M')}   | "
            f"{pair['exit']['price']:>10.6f} | "
            f"{exit_reason:<12} | "
            f"{pair['pnl_percent']:>8.2f} | "
            f"{pair.get('leveraged_pnl_percent', 0.0):>11.2f} | "
            f"{pair.get('pnl_amount', 0.0):>11.2f} | "
            f"{str(holding_period).split('.')[0]:<15} |\n"
        )
    
    trade_details_footer = "    -------------------------------------------------------------------------------------------------------------------------------------------------------"

    report += trade_details_header + trade_details_rows + trade_details_footer

    # --- 2. 计算和添加综合统计信息 ---
    # 先进行基础计算
    total_trades = len(all_trades)
    win_trades = [p for p in all_trades if p['pnl_percent'] > 0]
    loss_trades = [p for p in all_trades if p['pnl_percent'] <= 0]
    
    win_rate = len(win_trades) / total_trades * 100 if total_trades > 0 else 0
    
    avg_win_pnl = np.mean([p.get('leveraged_pnl_percent', p['pnl_percent'] * 30) for p in win_trades]) if win_trades else 0
    avg_loss_pnl = np.mean([p.get('leveraged_pnl_percent', p['pnl_percent'] * 30) for p in loss_trades]) if loss_trades else 0
    
    profit_loss_ratio = abs(avg_win_pnl / avg_loss_pnl) if avg_loss_pnl and avg_loss_pnl != 0 else float('inf')
    
    # 计算最大单笔盈利和亏损
    max_win = max([p.get('leveraged_pnl_percent', p['pnl_percent'] * 30) for p in win_trades]) if win_trades else 0
    max_loss = min([p.get('leveraged_pnl_percent', p['pnl_percent'] * 30) for p in loss_trades]) if loss_trades else 0
    
    # 计算持仓时间
    holding_periods = [(p['exit']['datetime'] - p['entry']['datetime']) for p in all_trades]
    avg_holding_period = np.mean([h.total_seconds() for h in holding_periods]) / 3600 if holding_periods else 0  # 转换为小时

    # 计算总手续费和总收益
    total_fees = sum([p.get('fees', 0) for p in all_trades])
    total_pnl = sum([p.get('pnl_amount', 0) for p in all_trades])
    
    # 最大回撤估算 (使用净值曲线)
    balance = 10000  # 假设初始资金10000 USDT
    equity_curve = [balance]
    peak = balance
    max_drawdown = 0
    
    # 按时间顺序依次计算净值
    for p in all_trades:
        pnl = p.get('pnl_amount', balance * p['pnl_percent'] / 100)
        balance += pnl
        equity_curve.append(balance)
        
        # 更新峰值和回撤
        if balance > peak:
            peak = balance
        else:
            dd = (peak - balance) / peak * 100
            if dd > max_drawdown:
                max_drawdown = dd

    # 计算按币种分组的统计
    symbol_stats = {}
    for p in all_trades:
        symbol = p['symbol']
        if symbol not in symbol_stats:
            symbol_stats[symbol] = {'count': 0, 'win': 0, 'loss': 0, 'total_pnl': 0}
        
        symbol_stats[symbol]['count'] += 1
        if p['pnl_percent'] > 0:
            symbol_stats[symbol]['win'] += 1
        else:
            symbol_stats[symbol]['loss'] += 1
        symbol_stats[symbol]['total_pnl'] += p.get('pnl_amount', 0)

    # 添加统计信息到报告
    report += f"""
    
    ========================================================================
    |                           策略综合统计                              |
    ========================================================================
    
    基本交易统计:
    ----------------------------------------------------------------------
    总交易次数:     {total_trades}
    胜率:           {win_rate:.2f}%
    盈亏比:         {profit_loss_ratio:.2f}
    平均每笔盈利:   {avg_win_pnl:.2f}% 
    平均每笔亏损:   {avg_loss_pnl:.2f}% 
    最大单笔盈利:   {max_win:.2f}% 
    最大单笔亏损:   {max_loss:.2f}% 
    平均持仓时间:   {avg_holding_period:.2f} 小时
    
    风险收益指标:
    ----------------------------------------------------------------------
    总盈亏金额:     {total_pnl:.2f} USDT
    总手续费:       {total_fees:.2f} USDT
    平均每笔手续费: {total_fees/total_trades:.2f} USDT
    最大回撤:       {max_drawdown:.2f}%
    
    分币种统计:
    ----------------------------------------------------------------------"""
    
    for symbol, stats in symbol_stats.items():
        symbol_win_rate = stats['win'] / stats['count'] * 100 if stats['count'] > 0 else 0
        report += f"""
    {symbol:<10}: 交易 {stats['count']:>3} 次, 胜率 {symbol_win_rate:>6.2f}%, 盈亏 {stats['total_pnl']:>8.2f} USDT"""
    
    # 添加同时持有币种的统计信息
    report += f"""

    仓位统计:
    ----------------------------------------------------------------------
    同一时间最多持有: {max_concurrent} 个币种"""
    
    if max_concurrent > 0 and max_time:
        report += f"""
    发生时间: {max_time.strftime('%Y-%m-%d %H:%M')}
    持仓详情:"""
        for symbol, direction in max_details.items():
            report += f"""
      - {symbol}: {direction}"""
    
    print(report)

def analyze_concurrent_positions(all_trades):
    """
    分析同一时间内持有的最大币种数量
    
    参数:
        all_trades: 所有交易对的列表
        
    返回:
        最大同时持有的币种数量和详情
    """
    if not all_trades:
        return 0, {}
    
    # 按照时间顺序整理所有的开仓和平仓事件
    events = []
    for pair in all_trades:
        symbol = pair['symbol']
        # 添加开仓事件
        events.append({
            'datetime': pair['entry']['datetime'],
            'symbol': symbol,
            'action': 'open',
            'direction': pair['entry']['direction']
        })
        # 添加平仓事件
        events.append({
            'datetime': pair['exit']['datetime'],
            'symbol': symbol,
            'action': 'close',
            'direction': pair['entry']['direction']
        })
    
    # 按时间排序所有事件
    events.sort(key=lambda x: x['datetime'])
    
    # 跟踪当前持仓的币种
    current_positions = {}  # 格式: {symbol: direction}
    max_concurrent = 0
    max_concurrent_time = None
    max_concurrent_details = {}
    
    # 遍历事件
    for event in events:
        symbol = event['symbol']
        action = event['action']
        
        if action == 'open':
            # 开仓：添加持仓记录
            current_positions[symbol] = event['direction']
        elif action == 'close' and symbol in current_positions:
            # 平仓：移除持仓记录
            del current_positions[symbol]
        
        # 检查是否创新高
        current_count = len(current_positions)
        if current_count > max_concurrent:
            max_concurrent = current_count
            max_concurrent_time = event['datetime']
            max_concurrent_details = current_positions.copy()
    
    return max_concurrent, max_concurrent_details, max_concurrent_time

async def test_sar_strategy(symbol: str, days: int, show_details: bool):
    """
    测试SAR策略 (强制回测模式)
    
    Args:
        symbol: 交易对
        days: 回测天数
    """
    # 从数据库加载测试数据
    logger.info("准备测试数据...")
    
    # 根据天数计算需要的K线数量（每天288根5分钟K线）
    limit = days * 288
    
    db = SessionLocal()
    strategy_params = None
    try:
        # 1. 从数据库获取策略配置
        logger.info(f"正在为 {symbol} 从数据库加载策略配置...")
        config = db.query(StrategyConfig).filter(
            StrategyConfig.strategy_name == 'SARStrategy',
            StrategyConfig.symbol == symbol.replace("-","_"),
            StrategyConfig.is_active == 1
        ).first()
        if config and config.parameters_json:
            param_string = config.parameters_json
            try:
                # 1. 使用正则表达式移除注释并添加缺失的逗号
                # 匹配模式: (值)(注释)(下一个token的开始符) -> (值),(下一个token的开始符)
                # 值可以是: True, False, 数字, 或单引号字符串
                # 下一个token的开始符可以是: ' 或 }
                cleaned_string = re.sub(r"((?:True|False|[\d.-]+|'[^']*'))(#.*?)(['}])", r"\1,\3", param_string)
                
                # 2. 使用ast.literal_eval安全地解析修复后的字符串为Python字典
                strategy_params = ast.literal_eval(cleaned_string)
                logger.info(f"成功为 {symbol} 加载并修复了数据库配置。")

            except Exception as e:
                logger.error(f"修复并解析数据库配置时出错: {e}。将使用脚本内默认参数。")
                logger.debug(f"问题字符串: {param_string}")
                strategy_params = None
        else:
            logger.warning(f"未在数据库中找到 {symbol} 的有效策略配置，将使用脚本内默认参数。")

        # 2. 从数据库加载指定交易对和天数的5分钟K线数据
        df = load_data_from_db(db, symbol, limit=limit)
    except Exception as e:
        logger.error(f"加载数据或配置失败: {e}")
        return
    finally:
        db.close()
    
    # 如果数据库中没有配置，则使用硬编码的默认参数
    if strategy_params is None:
        strategy_params = {
            'initial_take_profit': 0.002,
            'step_trigger_percent': 0.003,
            'step_take_profit_increment': 0.002,
            'sar_entry_offset_pct': 1.5,
            'sar_exit_n2': 2.0,
            'sar_exit_n3': 2.0,
            'sar_exit_n4': 7.0,
            'sar_entry1_n2': 2.0,
            'sar_entry1_n3': 2.0,
            'sar_entry1_n4': 4.0,
            'sar_entry2_n2': 2.0,
            'sar_entry2_n3': 2.0,
            'sar_entry2_n4': 5.0,
            'sar_filter_n2': 2.0,
            'sar_filter_n3': 2.0,
            'sar_filter_n4': 3.0,
            'supertrend_periods': 10,
            'supertrend_multiplier': 3.9,
            'supertrend_source': 'hl2',
            'hard_stop_loss_pct': 0.008,  # 设置0.8%的硬止损
        }
    
    # 强制使用回测模式，覆盖数据库中的任何相关设置
    strategy_params['use_backtest_exit_mode'] = True
    strategy_params['use_backtest_entry_mode'] = True

    logger.info(f"初始化 {symbol} 的SAR策略 (回测天数: {days}, 模式: 回测)...")
    strategy = SARStrategy(symbol, parameters=strategy_params)
    
    # 准备数据（计算指标）
    logger.info("计算指标...")
    prepared_data = strategy.prepare_data(df)
    
    # 测试策略信号
    logger.info("测试策略信号...")
    
    # 存储交易记录
    trades = []
    current_position = None
    entry_data = None
    
    # 从第100根K线开始回测，确保有足够数据计算指标
    for i in range(100, len(prepared_data)):
        chunk = prepared_data.iloc[:i+1]
        
        # 检查是否应该平仓
        if current_position:
            has_exit, exit_signal = await strategy.check_exit_signal(chunk, entry_data)
            if has_exit:
                exit_dt = pd.to_datetime(exit_signal['datetime'])
                logger.info(f"[{exit_dt}] 平仓信号: {exit_signal['reason']}")
                
                # 直接使用信号中的价格
                trades.append({
                    'type': 'exit',
                    'direction': current_position,
                    'datetime': exit_dt,
                    'price': exit_signal['price'],
                    'reason': exit_signal['reason']
                })
                current_position = None
                entry_data = None
                continue
        
        # 如果没有持仓，检查是否应该开仓
        if not current_position:
            has_entry, entry_signal = await strategy.check_entry_signal(chunk)
            if has_entry:
                current_position = entry_signal['direction']
                entry_data = entry_signal
                entry_dt = pd.to_datetime(entry_signal['datetime'])
                
                # 构建开仓日志信息，包含前一根K线的SAR值和硬止损价格
                entry_log = f"[{entry_dt}] 开仓信号: {entry_signal['direction']}, {entry_signal['reason']}"
                if 'hard_stop_loss_price' in entry_signal:
                    entry_log += f" | 硬止损价: {entry_signal['hard_stop_loss_price']:.2f} ({entry_signal['hard_stop_loss_pct']:.2f}%)"
                
                logger.info(entry_log)
                
                trades.append({
                    'type': 'entry',
                    'direction': current_position,
                    'datetime': entry_dt,
                    'price': entry_signal['price'],
                    'reason': entry_signal['reason'],
                    'hard_stop_loss_price': entry_signal.get('hard_stop_loss_price')
                })
    
    # 计算策略结果
    if trades:
        entry_trades = [t for t in trades if t['type'] == 'entry']
        exit_trades = [t for t in trades if t['type'] == 'exit']
        
        # 创建交易对
        completed_pairs = []
        for i in range(min(len(entry_trades), len(exit_trades))):
            entry = entry_trades[i]
            exit = exit_trades[i]
            pnl = 0
            if entry['direction'] == '多':
                pnl = (exit['price'] - entry['price']) / entry['price'] * 100
            else:
                pnl = (entry['price'] - exit['price']) / entry['price'] * 100
                
            completed_pairs.append({
                'entry': entry,
                'exit': exit,
                'pnl_percent': pnl
            })
        
        # 生成并打印回测报告
        generate_backtest_report(completed_pairs, prepared_data, symbol, days, show_details=show_details)
        return completed_pairs
    else:
        logger.info("沒有產生交易信號")
        return []

    logger.info(f"对 {symbol} 的回测完成")

async def main():
    """主函数，用于解析参数和执行多币种回测"""
    parser = argparse.ArgumentParser(description="多币种SAR策略回测")
    parser.add_argument("--symbols", type=str, nargs='+', default=["ETH-USDT", "BTC-USDT"], 
                        help="要回测的交易对列表，例如: --symbols BTC-USDT ETH-USDT")
    parser.add_argument("--days", type=int, default=30, help="要回测的最近天数")
    parser.add_argument("--summary-only", action="store_true", 
                        help="仅显示最终总汇报告，隐藏所有中间回测过程")
    args = parser.parse_args()
    
    # 处理日志级别设置
    original_level = logger.getEffectiveLevel()
    if args.summary_only:
        # 临时调整日志级别，禁止INFO级别输出
        logger.setLevel(logging.WARNING)

    all_trades = []
    for symbol in args.symbols:
        if not args.summary_only:
            logger.info(f"\n{'='*30} 开始回测: {symbol} {'='*30}")
        completed_pairs = await test_sar_strategy(symbol=symbol, days=args.days, show_details=not args.summary_only)
        # 为每个交易对添加symbol标识，并收集
        for pair in completed_pairs:
            pair['symbol'] = symbol
        all_trades.extend(completed_pairs)
        if not args.summary_only:
            logger.info(f"{'='*30} 回测结束: {symbol} {'='*30}\n")
    
    # 回测完成后恢复日志级别
    logger.setLevel(original_level)
    
    # 在所有回测结束后，打印总汇报告
    if all_trades:
        print("\n\n")  # 确保与前面的日志有充分间隔
        generate_summary_report(all_trades)
    else:
        print("没有找到任何交易记录。")

if __name__ == "__main__":
    asyncio.run(main()) 